﻿using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using Core.Helper;

namespace Core.Model.Transmit
{

    [DataContract]
    public class TransmitData : INotifyPropertyChanged
    {
        // not store in db
        public event PropertyChangedEventHandler PropertyChanged;

        #region field

        private string _id;

        private string _name;

        private int _address;

        //private Access _access;

        private string _deviceId;

        private string _sourceId;

        private PhyType _phyType = PhyType.模拟量;

        private DataType _dataType = DataType.Int32;

       
        private string _subInfo;

        private Extra _tagObject;

        private object _value;

        private double _curValue;

        private double _coefficient = 1;

        private DateTime _updateTime;

        #endregion

        #region property
        [DisplayName("唯一ID")]
        [Browsable(false)]
        [DataMember]
        public string Id
        {
            get => _id;
            set
            {
                if (_id != value)
                {
                    _id = value;
                    NotifyPropertyChanged("Id");
                }
            }
        }
        [DisplayName("数据名称")]
        [DataMember]
        public string Name
        {
            get => _name;
            set
            {
                if (_name != value)
                {
                    _name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }
        [ReadOnly(true)]
        [DisplayName("数据序号")]
        [DataMember]
        public int Position { get; set; }
        [DisplayName("数据地址")]
        //[DataMember]
        public int Address
        {
            get => _address;
            set
            {
                if (_address != value)
                {
                    _address = value;
                    NotifyPropertyChanged("Address");
                }
            }
        }
        //[DisplayName("权限")]
        //[DataMember]
        //public Access Access
        //{
        //    get => _access;
        //    set
        //    {
        //        if (_access != value)
        //        {
        //            _access = value;
        //            NotifyPropertyChanged("Access");
        //        }
        //    }
        //}
        [ReadOnly(true)]
        [DisplayName("设备ID")]
        [DataMember]
        public string DeviceId
        {
            get => _deviceId;
            set
            {
                if (_deviceId != value)
                {
                    _deviceId = value;
                    NotifyPropertyChanged("DeviceId");
                }
            }
        }
        [ReadOnly(true)]
        [DisplayName("源数据ID")]
        [DataMember]
        public string SourceId
        {
            get => _sourceId;
            set
            {
                if (_sourceId != value)
                {
                    _sourceId = value;
                    NotifyPropertyChanged("SourceId");
                }
            }
        }
        [DisplayName("物理归类")]
        [DataMember]
        public PhyType PhyType
        {
            get => _phyType;
            set
            {
                if (_phyType != value)
                {
                    _phyType = value;
                    NotifyPropertyChanged("PhyType");
                }
            }
        }
        [DisplayName("数值类型")]
        //[DataMember]
        public DataType DataType
        {
            get => _dataType;
            set
            {
                if (_dataType != value)
                {
                    _dataType = value;
                    NotifyPropertyChanged("DataType");
                }
            }
        }
       
        /// <summary>
        /// 附加信息，由TagObject转Json而来，用于存储到数据库
        /// </summary>
        [Browsable(false)]
        //[DataMember]
        public string SubInfo
        {
            get => _subInfo;
            set
            {
                if (_subInfo != value)
                {
                    _subInfo = value;
                    NotifyPropertyChanged("SubInfo");
                }
            }
        }
        /// <summary>
        /// 附加信息，若无可不处理
        /// </summary>
        [DisplayName("附加属性")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public Extra TagObject
        {
            get => _tagObject;
            set => _tagObject = value;
        }
        [ReadOnly(true)]
        [DisplayName("当前值")]
        public object Value
        {
            get => _value;
            set
            {
                if (_value != value)
                {
                    _value = value;
                    try
                    {
                        NotifyPropertyChanged("Value");
                    }
                    catch
                    {
                    }
                }
            }
        }
        [ReadOnly(true)]
        [DisplayName("当前数值")]
        public double CurValue
        {
            get => _curValue;
            set
            {
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (value != _curValue)
                {
                    _curValue = value;
                    Value = _curValue;
                    NotifyPropertyChanged("CurValue");
                }
                else
                {
                    if (Value == null)
                    {
                        Value = _curValue;
                    }
                }
                UpdateTime = DateTime.Now;
            }
        }
       
        [DisplayName("倍率")]
        public double Coefficient
        {
            get => _coefficient;
            set
            {
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (value != _coefficient)
                {
                    _coefficient = value;
                    NotifyPropertyChanged("Coefficient");
                }   
            }
        }

        [ReadOnly(true)]
        [DisplayName("更新时间")]
        public DateTime UpdateTime
        {
            get => _updateTime;
            set
            {
                if (_updateTime != value)
                {
                    _updateTime = value;
                    NotifyPropertyChanged("UpdateTime");
                }
            }
        }

        #endregion

        public TransmitData()
        {
            this.Id = IdHelper.GuidToString();
        }

        public TransmitData(string name,string devId)
        {
            this.Id = IdHelper.GuidToString();
            this.Name = name;
            this.DeviceId = devId;
        }
        public TransmitData(TransmitData src)
        {
            this.Id = IdHelper.GuidToString();
            this.Name = "新数据项";
            this.DeviceId = src.DeviceId;
            //this.Access = src.Access;
            this.PhyType = src.PhyType;
            this.Position = src.Position + 1;
            this.TagObject = src.TagObject;
            this.DataType = src.DataType;
            
            switch (this.DataType)
            {
                case DataType.Byte:
                case DataType.Sbyte:
                    this.Address = src.Address;
                    break;
                case DataType.Int16:
                case DataType.UInt16:
                case DataType.BCD2:
                    this.Address = src.Address + 1;
                    break;
                case DataType.Int32:
                case DataType.UInt32:
                case DataType.Single:
                case DataType.BCD4:
                    this.Address = src.Address + 2;
                    break;
                case DataType.Int64:
                case DataType.UInt64:
                case DataType.Double:
                    this.Address = src.Address + 4;
                    break;
                default:
                    this.Address = src.Address + 1;
                    break;
            }
        }

        public TransmitData Clone(string newId,string devId)
        {
            TransmitData dataItem = new TransmitData();
            dataItem.Id = newId;
            dataItem.Name = Name;
            //dataItem.Access = Access;
            dataItem.Address = Address;
            dataItem.DataType = DataType;
            dataItem.DeviceId = devId;
            dataItem.PhyType = PhyType;
            dataItem.Position = Position;
            dataItem.SubInfo = SubInfo;
            return dataItem;
        }
        protected void NotifyPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(name));
        }
       
        public int GetDataLength()
        {
            int len;
            switch (this.DataType)
            {
                case DataType.Byte:
                case DataType.Sbyte:
                    len = 1;
                    break;
                case DataType.Int16:
                case DataType.UInt16:
                case DataType.BCD2:
                    len = 2;
                    break;
                case DataType.Int32:
                case DataType.UInt32:
                case DataType.Single:
                case DataType.BCD4:
                    len = 4;
                    break;
                case DataType.Int64:
                case DataType.UInt64:
                case DataType.Double:
                    len = 8;
                    break;
                default:
                    len = 2;
                    break;
            }
            return len;
        }
    }


    
}
